package etxt2db.corpus;

import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import edu.cmu.minorthird.text.AnnotatorLoader;
import edu.cmu.minorthird.text.BasicTextLabels;
import edu.cmu.minorthird.text.Details;
import edu.cmu.minorthird.text.MutableTextLabels;
import edu.cmu.minorthird.text.Span;
import edu.cmu.minorthird.text.TextBase;
import edu.cmu.minorthird.text.Token;
import edu.cmu.minorthird.text.Trie;

public class CompleteTextLabels implements MutableTextLabels, Serializable {
	
	private MutableTextLabels primary;
	private MutableTextLabels secondary;
	
	private Map<String,Set<Span>> noTokenSpans = new HashMap<String,Set<Span>>();
	
	public CompleteTextLabels(MutableTextLabels prim, MutableTextLabels sec){
		primary = prim;
		secondary = sec;
	}
	
	public CompleteTextLabels(TextBase prim){
		primary = new BasicTextLabels(prim);
		secondary = new BasicTextLabels(prim);
	}
	

	@Override
	public void closeTypeInside(String arg0, Span arg1) {
		primary.closeTypeInside(arg0, arg1);
	}

	@Override
	public void defineTypeInside(String arg0, Span arg1, Iterator<Span> arg2) {
		primary.defineTypeInside(arg0, arg1, arg2);
	}

	@Override
	public void setTextBase(TextBase arg0) {
		primary.setTextBase(arg0);
	}

	@Override
	public void addToType(Span arg0, String arg1) {
		primary.addToType(arg0, arg1);
	}
	
	public void addNoTokenToType(NoTokenSpan arg0, String arg1) {
		if(noTokenSpans.containsKey(arg1)){
			Set<Span> spans = noTokenSpans.get(arg1);
			spans.add(arg0);
		}else{
			Set<Span> spans = new HashSet<Span>();
			spans.add(arg0);
			noTokenSpans.put(arg1, spans);
		}
	}

	@Override
	public void addToType(Span arg0, String arg1, Details arg2) {
		primary.addToType(arg0, arg1, arg2);
	}

	@Override
	public void declareType(String arg0) {
		primary.declareType(arg0);
	}

	@Override
	public void defineDictionary(String arg0, Set<String> arg1) {
		primary.defineDictionary(arg0, arg1);
	}

	@Override
	public void defineDictionary(String arg0, List<String> arg1, boolean arg2) {
		primary.defineDictionary(arg0, arg1, arg2);
	}

	@Override
	public void defineTrie(List<String> arg0) {
		primary.defineTrie(arg0);
	}

	@Override
	public AnnotatorLoader getAnnotatorLoader() {
		return primary.getAnnotatorLoader();
	}

	@Override
	public Trie getTrie() {
		return primary.getTrie();
	}

	@Override
	public void setAnnotatedBy(String arg0) {
		primary.setAnnotatedBy(arg0);
	}

	@Override
	public void setAnnotatorLoader(AnnotatorLoader arg0) {
		primary.setAnnotatorLoader(arg0);
	}

	@Override
	public void setProperty(Token arg0, String arg1, String arg2) {
		primary.setProperty(arg0, arg1, arg2);
	}

	@Override
	public void setProperty(Span arg0, String arg1, String arg2) {
		primary.setProperty(arg0, arg1, arg2);

	}

	@Override
	public void setProperty(Token arg0, String arg1, String arg2, Details arg3) {
		primary.setProperty(arg0, arg1, arg2, arg3);
	}

	@Override
	public void setProperty(Span arg0, String arg1, String arg2, Details arg3) {
		primary.setProperty(arg0, arg1, arg2, arg3);
	}

	@Override
	public void annotateWith(String arg0, String arg1) {
		primary.annotateWith(arg0, arg1);
	}

	@Override
	public Iterator<Span> closureIterator(String arg0) {
		return primary.closureIterator(arg0);
	}

	@Override
	public Iterator<Span> closureIterator(String arg0, String arg1) {
		return primary.closureIterator(arg0, arg1);
	}

	@Override
	public Details getDetails(Span arg0, String arg1) {
		return primary.getDetails(arg0, arg1);
	}

	@Override
	public String getProperty(Token arg0, String arg1) {
		return primary.getProperty(arg0, arg1);
	}

	@Override
	public String getProperty(Span arg0, String arg1) {
		return primary.getProperty(arg0, arg1);
	}

	@Override
	public Set<String> getSpanProperties() {
		return primary.getSpanProperties();
	}

	@Override
	public Iterator<Span> getSpansWithProperty(String arg0) {
		return primary.getSpansWithProperty(arg0);
	}

	@Override
	public Iterator<Span> getSpansWithProperty(String arg0, String arg1) {
		return primary.getSpansWithProperty(arg0, arg1);
	}

	@Override
	public TextBase getTextBase() {
		return primary.getTextBase();
	}

	@Override
	public Set<String> getTokenProperties() {
		return primary.getTokenProperties();
	}

	@Override
	public Set<Span> getTypeSet(String arg0, String arg1) {
		Set<Span> result = new HashSet<Span>();
		for(Span spn : primary.getTypeSet(arg0, arg1)){
			result.add(spn);
		}
		if(noTokenSpans.containsKey(arg0)){
			for(Span spn : noTokenSpans.get(arg0)){
				if(spn.getDocumentId().equals(arg1)){
					result.add(spn);
				}
			}
		}
		return result;
	}

	@Override
	public Set<String> getTypes() {
		Set<String> types = noTokenSpans.keySet();
		Set<String> primaryTypes = primary.getTypes();
		Set<String> result = new HashSet<String>();
		result.addAll(types);
		result.addAll(primaryTypes);
		return result;
	}

	@Override
	public boolean hasDictionary(String arg0) {
		return primary.hasDictionary(arg0);
	}

	@Override
	public boolean hasType(Span arg0, String arg1) {
		return primary.hasType(arg0, arg1);
	}

	@Override
	public boolean inDict(Token arg0, String arg1) {
		return primary.inDict(arg0, arg1);
	}

	@Override
	public Iterator<Span> instanceIterator(String arg0) {
		return primary.instanceIterator(arg0);
	}

	@Override
	public Iterator<Span> instanceIterator(String arg0, String arg1) {
		return primary.instanceIterator(arg0, arg1);
	}

	@Override
	public boolean isAnnotatedBy(String arg0) {
		return primary.isAnnotatedBy(arg0);
	}

	@Override
	public boolean isType(String arg0) {
		return primary.isType(arg0);
	}

	@Override
	public void require(String arg0, String arg1) {
		primary.require(arg0, arg1);
	}

	@Override
	public void require(String arg0, String arg1, AnnotatorLoader arg2) {
		primary.require(arg0, arg1, arg2);
	}

	@Override
	public String showTokenProp(TextBase arg0, String arg1) {
		return primary.showTokenProp(arg0, arg1);
	}
	
	public String toString(){
		return primary.toString();
	}
	
	public MutableTextLabels getSecondaryLabels(){
		return secondary;
	}

}
